#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>

#include <base/helper.h>

namespace recognition {

unsigned char* ReadBitmapImageFile(const char *name) {
	FILE *filePtr;						//our file pointer
	BITMAPFILEHEADER bitmapFileHeader;	//our bitmap file header
	unsigned char *bitmapImage;  		//store image data

	filePtr = fopen(name,"rb");
	if (filePtr == NULL)
		return NULL;

	//read the bitmap file header
	fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER),1,filePtr);
//	printf("type: %x\n size: %x\n offset: %x\n", bitmapFileHeader.bfType, bitmapFileHeader.bfSize, bitmapFileHeader.bOffBits);

	// verify that this is a bmp file by check bitmap id
	if (bitmapFileHeader.bfType !=0x4D42) {
		fprintf(stderr, "Error! The provided file \"%s\" has different from bitmap image type! %i", name, bitmapFileHeader.bfType);
		fclose(filePtr);
		return NULL;
	}

	// Move file pointer to the begging of bitmap data
	fseek(filePtr, bitmapFileHeader.bOffBits, SEEK_SET);

	// Allocate enough memory for the bitmap image data
	bitmapImage = (unsigned char*) malloc(bitmapFileHeader.bfSize - bitmapFileHeader.bOffBits);

	// Read in the bitmap image data
	fread(bitmapImage, bitmapFileHeader.bfSize - bitmapFileHeader.bOffBits, 1, filePtr);

	// Make sure bitmap image data was read
	if (bitmapImage == NULL) {
		fprintf(stderr, "Error reading bitmap image from file \"%s\"", name);
		fclose(filePtr);
		return NULL;
	}

	// Close file and return bitmap image data
	if (fclose(filePtr) != 0) {
		fprintf(stderr, "Error closing the file \"%s\"", name);
	}

	return bitmapImage;
}

unsigned char* RawBmpToRgb(unsigned char *image, int height, int width) {
	unsigned char *res;
	int size = width * height * 3, x, y;
	res = (unsigned char*) malloc(size);

	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			int to = ((height - y - 1) * width + x) * 3;
			int from = (y * width + x) * 3;
			res[to] = image[from + 2];
			res[to + 1] = image[from + 1];
			res[to + 2] = image[from];
		}
	}

	return res;
}

unsigned char* ReadBmpRgb(const char *name, int height, int width) {
	unsigned char *bitmapImage, *res;

	bitmapImage = ReadBitmapImageFile(name);
	res = RawBmpToRgb(bitmapImage, height, width);

	free(bitmapImage);

	return res;
}

unsigned char* BmpRgbToGrayscale(unsigned char *image, int height, int width) {
	unsigned char *res;
	int size = width * height, x, y;
	res = (unsigned char*) malloc(size);

	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			int idx = y * width + x;
			int idx3 = idx * 3;
			unsigned char R, G, B, Y;
			R = image[idx3];
			G = image[idx3 + 1];
			B = image[idx3 + 2];

			Y = 0.299 * R + 0.587 * G + 0.114 * B;	// YUV
//			Y = 0.2125 * R + 0.7154 * G + 0.0721 * B; // BT.709

			res[idx] = Y;
//			printf("\n(x, y) = (%d, %d)   R=%d G=%d B=%d    Y=%d", x, y, R, G, B, Y);
		}
	}

	free(image);

	return res;
}

double* UcharToNormalizedDouble(unsigned char *image, int height, int width) {
	int size = height * width;
	double* res = (double*) malloc(sizeof(double) * size);
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			int index = y * width + x;
			res[index] = image[index]/255.0;
		}
	}

	return res;
}

double* MakeOdd(double *image, int &height, int &width) {
	int _width = width;
	height = height - (height + 1) % 2;
	width = width - (width + 1) % 2;
	int size = height * width;
	double* res = (double*) malloc(sizeof(double) * size);
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			int index_to = y * width + x;
			int index_from = y * _width + x;
			res[index_to] = image[index_from];
		}
	}

	return res;
}

}	// namespace recognition
